package com.tc.framework;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Auther: tianchao
 * @Date: 2020/11/2 13:33
 * @Description:
 */
public class MyApplicationContext {

    private Class configClass;

    Map<String,Object> map = new HashMap<String, Object>();

    private Map<String,BeanDefinition> beanDefinitionMap = new HashMap<String, BeanDefinition>();

    public MyApplicationContext(Class configClass){
        this.configClass = configClass;
        initBean();
    }

    private void initBean() {
        ClassLoader classLoader = MyApplicationContext.class.getClassLoader();
        if (configClass.isAnnotationPresent(ComponentScan.class)){
            ComponentScan annotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
            String[] value = annotation.value();
            for (String s : value) {
                String s1 = s.replaceAll("\\.", "\\/");
                URL resource = classLoader.getResource(s1);
                File file = new File(resource.getFile());
                List<File> fileClass = findFileClass(file);
                for (File aClass : fileClass) {
                    String absolutePath = aClass.getAbsolutePath();
                    if (absolutePath.endsWith(".class")) {
                        String substring = absolutePath.substring(
                                absolutePath.indexOf("classes")+"classes".length()+1,
                                absolutePath.lastIndexOf(".class")
                        ).replace("\\", ".");
                        Class<?> classObj = null;
                        try {
                            classObj = classLoader.loadClass(substring);
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                            continue;
                        }
                        if (classObj.isInterface()){
                            continue;
                        }
                        BeanDefinition beanDefinition = new BeanDefinition();
                        beanDefinition.setBeanClass(classObj);
                        if (classObj.isAnnotationPresent(Component.class)){
                            Component component = classObj.getAnnotation(Component.class);
                            String beanName;
                            if (component.value()!=null&&!"".equals(component.value())){
                                beanName = component.value();
                            }else{
                                beanName = generateBeanName(classObj);
                            }
                            if (classObj.isAnnotationPresent(Scope.class)){
                                Scope scope = classObj.getAnnotation(Scope.class);
                                String scopeStr = scope.value();
                                beanDefinition.setScope(scopeStr);
                            }else{
                                //无Scope
                                beanDefinition.setScope("singleton");
                            }
                            if (classObj.isAnnotationPresent(Lazy.class)){
                                Lazy lazy = classObj.getAnnotation(Lazy.class);
                                boolean lazyValue = lazy.value();
                                beanDefinition.setLazy(lazyValue);
                            }else{
                                beanDefinition.setLazy(false);
                            }

                            Object o = null;
                            try {
                                o = classObj.newInstance();
                            } catch (InstantiationException e) {
                                e.printStackTrace();
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            }
                            beanDefinitionMap.put(beanName,beanDefinition);
                            map.put(component.value(), o);
                        }
                    }
                }
            }
        }

    }

    private String generateBeanName(Class<?> classObj) {
        String simpleName = classObj.getSimpleName();
        String substring = simpleName.substring(0, 1);
        String s = substring.toLowerCase();
        return s + simpleName.substring(1);
    }

    /**
     * 目录
     * @param file
     * @return
     */
    private List<File> findFileClass(File file) {
        List<File> result = new ArrayList<File>();
        if (file.isDirectory()){
            File[] files = file.listFiles();
            for (File f : files) {
                result.addAll(findFileClass(f));
            }
        }else{
            result.add(file);
        }
        return result;
    }

    public Object getBean(String beanName) {
        if (!beanDefinitionMap.containsKey(beanName)){
            throw new RuntimeException("beanName 不存在");
        }
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        return map.get(beanName);
    }
}
